Visualization Project Part 1: Finding your Data¶


Locate a dataset that you are interested in working with. The data should be sufficiently complex that you can ask lots of questions about it and engage in creative design techniques, but not so complex that you need specialized hardware or algorithmic approaches to analyze. While you are welcome to use any data you’d like, I recommend that your datasets are tabular (e.g., CSV, TSV, SQL, etc.), contain 5,000 or fewer datapoints (on the order of one hundred or so tends to be sufficiently interesting without causing lag in Altair), and is data that you’re comfortable discussing as part of the course (e.g., avoid data that is overly private or classified).

Discuss your dataset, including the data’s source, key attributes/dimensions of the data, and your goals for working with that data (i.e., what are the key questions you want to answer). Identify existing relevant visualizations for working with that data (either using the same data, showing the same concepts, or just that might provide some inspiration) and critique those visualizations based on the practices from this module. What works well? What might need improvement or to change to answer your target questions?

Part 1 Answers:¶

Dataset details:¶

The dataset used is from the Union of Concerned Scientists (UCSUSA) which details all openly-known satellites orbitting the earth at the time of previous update - January 1, 2023.

  • Source: Accessed 12/1/2023 | UCS-Satellite-Database-Officialname-1-1-2023.csv | https://www.ucsusa.org/resources/satellite-database
  • 6718 satellites listed.
  • 68 Features (columns) for each satellite including name, country of owner, purpose, orbital information, launch information, etc..
    • Feature Appendix https://s3.amazonaws.com/ucs-documents/nuclear-weapons/sat-database/4-11-17-update/User+Guide+1-1-17+wAppendix.pdf
Preliminary Goals for this Data:¶
  • Determine which country has the most satellites in orbit currently and execute a method that allows users to reach increased depths of information through this visualization, likely through grouping/aggregating features.
  • Create a compelling way to identify orbital information about satellites. Look into different orbit features which may impact lifespan and/or see which orbiting altitudes are most congested.
  • Feature engineer interesting statistics about the age of the satellites using life expectancy and launch date information.
Existing Visualizations:¶

UCSUSA has a visualization highlighting each country on an image of a map that has satellites or not. They also distinguish between countries that launch satellites or not as well as have a slider depicting the same information from either 1966 or 2020. You can see it at the website above.

Pros:

  • This visualization works well for conveying which countries poses satellites at a glance, making it especially easy to find the answer for specific countries.
  • The color orange in juxtaposition to the grey map makes the information easily identifiable.
    • Also, the textured orange is holds all the positives previously mentioned while still being easily distinguishable from the normal orange.

Cons:

  • Country names are pretty small which may not be ideal for users unfamiliar with geography.
  • The slider used to switch between 1966 and 2020, while intuitive, seems frivolous. Especially since no mention of a purpose is mentioned.
  • Displaying a tooltip while hovering over each country giving more data would be a nice addition instead or in conjunction.

Overall, I believe it to be a successful visualization but has limited uses as it doesn't answer more interesting questions that live within this dataset. Giving the user the ability to reach more information depth through other methods of interaction would help improve this execution.

EDA and Data Cleaning¶

In [ ]:
# Import necessary packages and data.
import pandas as pd
import altair as alt
alt.data_transformers.enable('vegafusion')
from vega_datasets import data
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

sat_df = pd.read_csv('UCS-Satellite-Database-1-1-2023.csv')
country_codes_df = pd.read_csv('iso_3166_country_codes.csv')
In [ ]:
# Preliminary EDA
print(sat_df.shape)
print(sat_df.columns)
(6718, 68)
Index(['Name of Satellite, Alternate Names',
       'Current Official Name of Satellite', 'Country/Org of UN Registry',
       'Country of Operator/Owner', 'Operator/Owner', 'Users', 'Purpose',
       'Detailed Purpose', 'Class of Orbit', 'Type of Orbit',
       'Longitude of GEO (degrees)', 'Perigee (km)', 'Apogee (km)',
       'Eccentricity', 'Inclination (degrees)', 'Period (minutes)',
       'Launch Mass (kg.)', ' Dry Mass (kg.) ', 'Power (watts)',
       'Date of Launch', 'Expected Lifetime (yrs.)', 'Contractor',
       'Country of Contractor', 'Launch Site', 'Launch Vehicle',
       'COSPAR Number', 'NORAD Number', 'Comments', 'Unnamed: 28',
       'Source Used for Orbital Data', 'Source', 'Source.1', 'Source.2',
       'Source.3', 'Source.4', 'Source.5', 'Source.6', 'Unnamed: 37',
       'Unnamed: 38', 'Unnamed: 39', 'Unnamed: 40', 'Unnamed: 41',
       'Unnamed: 42', 'Unnamed: 43', 'Unnamed: 44', 'Unnamed: 45',
       'Unnamed: 46', 'Unnamed: 47', 'Unnamed: 48', 'Unnamed: 49',
       'Unnamed: 50', 'Unnamed: 51', 'Unnamed: 52', 'Unnamed: 53',
       'Unnamed: 54', 'Unnamed: 55', 'Unnamed: 56', 'Unnamed: 57',
       'Unnamed: 58', 'Unnamed: 59', 'Unnamed: 60', 'Unnamed: 61',
       'Unnamed: 62', 'Unnamed: 63', 'Unnamed: 64', 'Unnamed: 65',
       'Unnamed: 66', 'Unnamed: 67'],
      dtype='object')
In [ ]:
# Displays the owner of the most currently active satellites.
sat_df.groupby(['Country of Operator/Owner', 'Operator/Owner']).size().sort_values(ascending = False).head(20).reset_index()
Out[ ]:
Country of Operator/Owner Operator/Owner 0
0 USA SpaceX 3349
1 United Kingdom OneWeb Satellites 502
2 USA Planet Labs, Inc. 195
3 China Chinese Ministry of National Defense 147
4 USA Spire Global Inc. 127
5 Russia Ministry of Defense 99
6 USA Swarm Technologies 84
7 USA Iridium Communications, Inc. 75
8 China Chang Guang Satellite Technology Co. Ltd. 53
9 USA National Reconnaissance Office (NRO) 50
10 China China Academy of Space Technology (CAST) 49
11 USA Spacex 46
12 India Indian Space Research Organization (ISRO) 46
13 ESA European Space Agency (ESA) 40
14 USA ORBCOMM Inc. 35
15 USA DoD/US Air Force 34
16 USA Intelsat S.A. 34
17 USA Globalstar 33
18 Luxembourg SES S.A. 31
19 Argentina Satellogic S.A. 30
In [ ]:
# Check all column features for the amount of unique values.
sat_df = sat_df.drop(sat_df.iloc[:, 28:], axis = 1)
for col in sat_df:
    print(col, '|', sat_df[col].unique().size)
Name of Satellite, Alternate Names | 6709
Current Official Name of Satellite | 6698
Country/Org of UN Registry | 70
Country of Operator/Owner | 104
Operator/Owner | 639
Users | 20
Purpose | 31
Detailed Purpose | 53
Class of Orbit | 5
Type of Orbit | 9
Longitude of GEO (degrees) | 446
Perigee (km) | 783
Apogee (km) | 777
Eccentricity | 796
Inclination (degrees) | 450
Period (minutes) | 580
Launch Mass (kg.) | 567
 Dry Mass (kg.)  | 172
Power (watts) | 153
Date of Launch | 1187
Expected Lifetime (yrs.) | 29
Contractor | 560
Country of Contractor | 103
Launch Site | 39
Launch Vehicle | 164
COSPAR Number | 6707
NORAD Number | 6703
Comments | 1288
In [ ]:
# Clean up the data for use.
country_codes_df = country_codes_df.rename({'name' : 'Country of Operator/Owner'}, axis = 1)
country_codes_df = country_codes_df.rename({'country-code' : 'Country_Code'}, axis = 1)

# Start with the country codes dataframe to match what is used in the satellite data.
# This will help during the merge to add a country code column for use in maps.
# Should've just changed the .csv at this point but here we are.
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'United States of America', 'Country of Operator/Owner'] = 'USA'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'United Kingdom of Great Britain and Northern Ireland', 'Country of Operator/Owner'] = 'United Kingdom'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Russian Federation', 'Country of Operator/Owner'] = 'Russia'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Korea, Republic of', 'Country of Operator/Owner'] = 'South Korea'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Taiwan, Province of China', 'Country of Operator/Owner'] = 'Taiwan'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Iran (Islamic Republic of)', 'Country of Operator/Owner'] = 'Iran'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == "Lao People's Democratic Republic", 'Country of Operator/Owner'] = 'Laos'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Viet Nam', 'Country of Operator/Owner'] = 'Vietnam'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Venezuela (Bolivarian Republic of)', 'Country of Operator/Owner'] = 'Venezuela'
country_codes_df.loc[country_codes_df['Country of Operator/Owner'] == 'Bolivia (Plurinational State of)', 'Country of Operator/Owner'] = 'Bolivia'


# Satellite df cleaning. Mostly misspellings or duplicate categories.
# Country fixes
sat_df.loc[sat_df['Country of Operator/Owner'] == 'ESA/', 'Country of Operator/Owner'] = 'USA' # This is the Hubble Telescope!
sat_df.loc[sat_df['Country of Operator/Owner'] == 'Czech Republic', 'Country of Operator/Owner'] = 'Czechia'
sat_df.loc[sat_df['Country of Operator/Owner'] == 'China ', 'Country of Operator/Owner'] = 'China'
sat_df.loc[sat_df['Country of Operator/Owner'] == "Sinapore", 'Country of Operator/Owner'] = 'Singapore'
# Operator name fixes.
sat_df.loc[sat_df['Operator/Owner'] == "Spacex", 'Operator/Owner'] = 'SpaceX'
sat_df.loc[sat_df['Operator/Owner'] == "US Air Force ", 'Operator/Owner'] = 'US Air Force'
# Purpose category fixes.
sat_df.loc[sat_df['Purpose'] == "Earth Observation ", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Navigation", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Communications/Navigation", 'Purpose'] = 'Communications'
sat_df.loc[sat_df['Purpose'] == "Communications/Technology Development", 'Purpose'] = 'Communications'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Communications/Space Science", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Earth Observation/Space Science", 'Purpose'] = 'Earth Observation'
sat_df.loc[sat_df['Purpose'] == "Space Observation", 'Purpose'] = 'Space Science'
# Class of Orbit fixes.
sat_df.loc[sat_df['Class of Orbit'] == "LEo", 'Class of Orbit'] = 'LEO'
# Remove commas from continuos features as they don't play well with Vega-Altair.
sat_df['Launch Mass (kg.)'] = sat_df['Launch Mass (kg.)'].str.replace(',', '').astype(float)
sat_df['Apogee (km)'] = sat_df['Apogee (km)'].str.replace(',', '').astype(float)
sat_df['Perigee (km)'] = sat_df['Perigee (km)'].str.replace(',', '').astype(float)
sat_df['Period (minutes)'] = sat_df['Period (minutes)'].str.replace(',', '').astype(float)
# Inclination fixes.
sat_df.loc[sat_df['Inclination (degrees)'] == '1,436', 'Inclination (degrees)'] = '1.436'
sat_df.loc[sat_df['Inclination (degrees)'] == "USA", 'Inclination (degrees)'] = '0'
# Users Fixes
sat_df.loc[sat_df['Users'] == 'Military/Commercial', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Military/Government', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government/Civil', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Military/Civil', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Commercial/Civil', 'Users'] = 'Commercial'
sat_df.loc[sat_df['Users'] == 'Civil/Commercial', 'Users'] = 'Civil'
sat_df.loc[sat_df['Users'] == 'Commercial/Government', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Government/Commercial/Military', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Civil/Government', 'Users'] = 'Civil'
sat_df.loc[sat_df['Users'] == 'Civil/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Commercial ', 'Users'] = 'Commercial'
sat_df.loc[sat_df['Users'] == 'Commercial/Military', 'Users'] = 'Military'
sat_df.loc[sat_df['Users'] == 'Government ', 'Users'] = 'Government'
sat_df.loc[sat_df['Users'] == 'Military ', 'Users'] = 'Military'
# Apogee Fixes
sat_df.loc[sat_df['Apogee (km)'] == 353798, 'Apogee (km)'] = 35798 # Checked records, this was listed as GEO which made this apogee nonsense.

# Merge country info with satellite dataframe.
print(country_codes_df.head())
sat_df = sat_df.merge(country_codes_df, on = 'Country of Operator/Owner', how = 'left')
# Display and check if correct.
display(sat_df.head(2))
  Country of Operator/Owner alpha-3  Country_Code
0               Afghanistan     AFG             4
1             Åland Islands     ALA           248
2                   Albania     ALB             8
3                   Algeria     DZA            12
4            American Samoa     ASM            16
Name of Satellite, Alternate Names Current Official Name of Satellite Country/Org of UN Registry Country of Operator/Owner Operator/Owner Users Purpose Detailed Purpose Class of Orbit Type of Orbit ... Expected Lifetime (yrs.) Contractor Country of Contractor Launch Site Launch Vehicle COSPAR Number NORAD Number Comments alpha-3 Country_Code
0 1HOPSAT-TD (1st-generation High Optical Perfor... 1HOPSAT-TD NR USA Hera Systems Commercial Earth Observation Infrared Imaging LEO Non-Polar Inclined ... 0.5 Hera Systems USA Satish Dhawan Space Centre PSLV 2019-089H 44859 Pathfinder for planned earth observation const... USA 840.0
1 Aalto-1 Aalto-1 Finland Finland Aalto University Civil Technology Development NaN LEO Sun-Synchronous ... 2.0 Aalto University Finland Satish Dhawan Space Centre PSLV 2017-036L 42775 Technology development and education. FIN 246.0

2 rows × 30 columns

In [ ]:
# Ensure all countries have their proper codes by seeing which entries don't have one.
print(sat_df['Country of Operator/Owner'].where(sat_df['Country_Code'].isna()).unique())
[nan 'Multinational' 'ESA' 'USA/Argentina' 'France/Italy' 'China/Brazil'
 'China/France' 'USA/Canada/Japan' 'USA/Japan/Brazil' 'USA/Japan'
 'USA/Germany' 'France/Italy/Belgium/Spain/Greece' 'Greece/United Kingdom'
 'United Kingdom/ESA' 'USA/India/Singapore/Taiwan' 'ESA/Russia'
 'USA/France' 'Japan/Singapore' 'United Kingdom/Netherlands'
 'Morocco/Germany' 'India/France' 'USA/Canada' 'India/Canada'
 'France/Belgium/Sweden' 'Singapore/Taiwan' 'Poland/UK'
 'USA/United Kingdom/Italy' 'Turkmenistan/Monaco' 'France/Israel'
 'China/Italy']
In [ ]:
# Check to see how many satellites are co-owned.
# Will leave these out of the calculation for individual countries for now.
sat_df.loc[sat_df['Country_Code'].isna(), 'Country of Operator/Owner'].size
Out[ ]:
168
In [ ]:
# Check dates datatype for use later.
# Reformat into a datetime format.
print(sat_df['Date of Launch'].dtype)
sat_df.loc[sat_df['Date of Launch'] == '11/29/018', 'Date of Launch'] = '29-11-2018'
sat_df['Date of Launch'] = pd.to_datetime(sat_df['Date of Launch'], format = '%d-%m-%Y', errors = 'raise')
# Create a separate column for year of launch for easier utilization later.
sat_df['Year of Launch'] = pd.DatetimeIndex(sat_df['Date of Launch']).year

# Check date change for sanity check.
print(sat_df.iloc[1070])
object
Name of Satellite, Alternate Names    Hubble Space Telescope (HST, Space Telescope)
Current Official Name of Satellite                           Hubble Space Telescope
Country/Org of UN Registry                                                      USA
Country of Operator/Owner                                                       USA
Operator/Owner                                     European Space Agency (ESA)/NASA
Users                                                                    Government
Purpose                                                               Space Science
Detailed Purpose                                                                NaN
Class of Orbit                                                                  LEO
Type of Orbit                                                    Non-Polar Inclined
Longitude of GEO (degrees)                                                      0.0
Perigee (km)                                                                  555.0
Apogee (km)                                                                   559.0
Eccentricity                                                               0.000289
Inclination (degrees)                                                          28.5
Period (minutes)                                                               95.8
Launch Mass (kg.)                                                           11110.0
 Dry Mass (kg.)                                                                 NaN
Power (watts)                                                              2,400.00
Date of Launch                                                  1990-04-25 00:00:00
Expected Lifetime (yrs.)                                                       10.0
Contractor                                               European Space Agency/NASA
Country of Contractor                                                 International
Launch Site                                                          Cape Canaveral
Launch Vehicle                                               Space Shuttle (STS 31)
COSPAR Number                                                             1990-037B
NORAD Number                                                                  20580
Comments                                                      Exploration of space.
alpha-3                                                                         USA
Country_Code                                                                  840.0
Year of Launch                                                                 1990
Name: 1070, dtype: object

Visualization Project Part 2: Sketching your Data¶


Your Module 1 discussion post identified some high-level goals for working with a dataset of interest to you. In this post, you will expand on those goals to characterize your target problem and develop some low-fidelity prototypes for working with that data. First, identify two to three tasks you would wish to complete with your data, identifying:

  1. Why is a task pursued? (goal)

  2. How is a task conducted? (means)

  3. What does a task seek to learn about the data? (characteristics)

  4. Where does the task operate? (target data)

  5. When is the task performed? (workflow)

  6. Who is executing the task? (roles)

  7. Then, sketch a set of preliminary low-fidelity prototypes for addressing these tasks with the given data. You may either sketch freeform or use the Five Design Sheets approach to generate these prototypes (hand-sketched on paper is fine). Upload a copy of your sketches as part of your post.

Part 2 Answers:¶

Sketching Tasks:¶

Using the information gained by the high-level exploratory data analysis performed in part 1, the examples found from the data source, and preliminary sketching done for possible tasks we will now flesh out the tasks for this data.

  • Task 1: Data overview displaying key features organized by country.

    • Why is this task pursued? - To gain a more granular knowledge about what types of satellites are currently active and orbitting earth, who owns them, and how this number is changing through time.
    • How is this task conducted? - By applying high-level aggregation on the data and grouping out features based on user selection.
    • What does this task seek to learn about the data? - High-level insights that lead to deeper insights including differences in feature distribution between countries.
    • Where does this task operate? - This task operates across the entire dataset aggregating by country and a few deeper features organized by country.
    • When is this task performed? - To be performed to supplement exploratory data analysis for someone who will be working with this dataset.
    • Who is executing this task? - Possible roles who might interface with this task are science journalists, political scientists, or government agencies looking for an overview of the world's satellite fleet.
  • Task 2: Using dates of launch and life expectancy, display age statistics across features

    • Why is this task pursued? - To help understand the age distribution of satellites and attempt to gain deeper insights about how different satellite types, countries, or orbital classes have been prioritized and how that might have changed. In short, analyze how current satellites have aged across different features.
    • How is this task conducted? - Using the date of launch and life expectancy given based on hardward/technology, fuel consumption, and orbital mechanics of the satellite, calculate the remaining life expectancy (or lack there of) while comparing it to country, orbit, purpose, etc.
    • What does this task seek to learn about the data? - Show how each country's/sector/etc satellite programs have grown or stagnated throughout time. Determine what, how many, which type of satellite has exceeded their life expectancy.
    • Where does this task operate? - Across many features of the dataset, aggregating upon dates and other categorical variables.
    • When is this task performed? - This task would be performed annually to track changes in active satellites as they age and degrade and new satellites are launched.
    • Who is executing this task? - Roles who would be interested in this task are similar to the first task, science journalists, political scientists, or government agencies.
  • Task 3: Calculate and visualize orbital paths of active satellites.

    • Why is this task pursued? - To help visualize the distribution of active satellite orbital paths for altitude congestion analysis.
    • How is this task conducted? - Using apogee, perigee, and eccentricity data calculate and plot each orbit.
    • What does this task seek to learn about the data? - Which class of orbit/altitudes are the most congested with satellite traffic.
    • Where does this task operate? - Orbit features in the data - apogee, perigee, and eccentricity.
    • When is this task performed? - Could possibly be performed when determining when a new satellite or spacecraft is launched.
    • Who is executing this task? - Public or private space agencies.

Visualizations¶

In [ ]:
# Let's see what the data looks like organized and sorted by country and total count.
print(sat_df.groupby(['Country of Operator/Owner', 'alpha-3', 'Country_Code']).size().sort_values(ascending = False).head(20))
Country of Operator/Owner  alpha-3  Country_Code
USA                        USA      840.0           4512
China                      CHN      156.0            587
United Kingdom             GBR      826.0            561
Russia                     RUS      643.0            177
Japan                      JPN      392.0             88
India                      IND      356.0             59
Canada                     CAN      124.0             56
Germany                    DEU      276.0             48
Luxembourg                 LUX      442.0             45
Argentina                  ARG      32.0              38
Israel                     ISR      376.0             27
Spain                      ESP      724.0             26
France                     FRA      250.0             24
Finland                    FIN      246.0             23
South Korea                KOR      410.0             21
Italy                      ITA      380.0             15
Switzerland                CHE      756.0             15
Netherlands                NLD      528.0             14
Australia                  AUS      36.0              14
Brazil                     BRA      76.0              14
dtype: int64
In [ ]:
country_select = alt.selection_point(fields = ['Country of Operator/Owner'], value = 'USA')
country_title = alt.TitleParams('Total Number of Active Satellites by Country',
                 subtitle = ['Filter Country by clicking on corresponding bar.', '(Source Data Updated 1/2023)'])

# Country totals graph.
# Added interactivity to select country and show 3 graphs.
country_bar_graph = alt.Chart(sat_df, title = country_title
    ).transform_aggregate(
        groupby = ['Country of Operator/Owner'],
        count = 'count()'
    ).transform_window(
        rank = 'rank(count)',
        sort = [alt.SortField('count', order = 'descending')]
    ).transform_filter(
        (alt.datum.rank <= 29) #29
    ).mark_bar().encode(
        x = alt.X('Country of Operator/Owner:N', 
            sort = '-y'),
        y = alt.Y('count:Q', title = 'Number of Satellites (Log Scale)').scale(type = 'log'),
        color = alt.Color('Country of Operator/Owner:N', legend = None),#.scale(scheme = 'tableau20'),
        stroke = alt.condition(country_select, alt.ColorValue('black'), alt.Color('Country of Operator/Owner:N', legend = None)),
        strokeWidth = alt.condition(country_select, alt.value(1), alt.value(0.5)),
        text = alt.Text('count:Q'),
        opacity = alt.condition(country_select, alt.value(0.7), alt.value(0.4))
    ).add_params(country_select)#.properties(width = 1000)

# Selected country's operator/owner graph.
operator_title = alt.TitleParams('Number of Satellites by Operator/Owner')
operator_bar_graph = alt.Chart(sat_df, title = operator_title
    ).mark_bar().encode(
        y = alt.Y('Operator/Owner:N',
                sort = '-x'),
        x = alt.X('count():Q'),
        text = alt.Text('count():Q'),
        color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
    ).transform_filter(country_select)

# Selected country's purpose of satellite graph.
purpose_title = alt.TitleParams('Number of Satellites by Functionality')
purpose_bar_graph = alt.Chart(sat_df, title = purpose_title
    ).mark_bar().encode(
        x = alt.X('Purpose:N',
                sort = '-y'),
        y = alt.Y('count():Q'),
        text = alt.Text('count():Q'),
        color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
    ).transform_filter(country_select)

# Selected country's Users of satellite graph.
users_title = alt.TitleParams('Number of Satellites by Primary User')
users_bar_graph = alt.Chart(sat_df, title = users_title
    ).mark_bar().encode(
        x = alt.X('Users:N',
                sort = '-y'),
        y = alt.Y('count():Q'),
        text = alt.Text('count():Q'),
        color = alt.Color('count():O', legend = None).scale(scheme = 'warmgreys')
    ).transform_filter(country_select)

# Selected country's launches per year.
year_title = alt.TitleParams('Number of Satellites Launched per Year')
year_bar_graph = alt.Chart(sat_df, title = year_title
    ).mark_bar().encode(
        y = alt.Y('Year of Launch:O', 
                axis = alt.Axis(orient = 'right'), scale = alt.Scale(reverse = True)),
        x = alt.X('count():Q', scale = alt.Scale(reverse = True)),
        text = alt.Text('count():Q'),
        color = alt.condition(alt.datum.count == 0, alt.value('blue'), 'count():O', legend = None)
    ).transform_filter(country_select)

country_bar_graph = country_bar_graph + country_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
operator_bar_graph = operator_bar_graph + operator_bar_graph.mark_text(align = 'center', dx = 14, fontSize = 9)
users_bar_graph = users_bar_graph + users_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
purpose_bar_graph = purpose_bar_graph + purpose_bar_graph.mark_text(align = 'center', dy = -14, fontSize = 9)
year_bar_graph = year_bar_graph + year_bar_graph.mark_text(align = 'center', dx = -14, fontSize = 9)

(country_bar_graph) & (users_bar_graph  | purpose_bar_graph | year_bar_graph| operator_bar_graph)
Out[ ]:
In [ ]:
# sat_df[sat_df['Operator/Owner'].str.contains('National Aeronautics and Space')]
sat_df.loc[sat_df['Country of Operator/Owner'] == 'USA', 'Operator/Owner'].unique()
Out[ ]:
array(['Hera Systems', 'National Reconnaissance Office (NRO)',
       'US Air Force', 'Department of Homeland Security',
       'Aerospace Corporation',
       'Center for Atmospheric Sciences, Hampton University/NASA',
       'US Air Force Institute of Technology', 'SES S.A.',
       'SES S.A./Gogo', 'AMSAT-NA', 'ANDESITE - Boston University',
       'University of South Florida, Institute of Applied Engineering (IAE).',
       'Planetary Resources', '1Worldspace', 'Astranis', 'DirecTV, Inc.',
       'PointView Tech', 'Salish Kootenai College', 'BlackSky Global',
       'AST SpaceMobile', 'SpaceQuest, Ltd.',
       'Capital Technology University',
       'University of Louisiana at Lafayette', 'Capella Space',
       'Air Force Research Laboratory',
       'NASA Goddard Space Flight Center',
       'Defense Innovation Unit/Cesium Astro',
       'National Aeronautics and Space Administration (NASA) Goddard Space Flight Center',
       'University of Florida', 'GeoOptics Inc.', 'GeoOptics, Inc.',
       'University of California-Berkeley/Imperial College-London',
       'Utah State University', 'Unknown US agency',
       'National Aeronautics and Space Administration (NASA)/Colorado State University',
       'Department of Defense/Missile Defense Agency',
       'US Air Force/ US Navy/NASA', 'Astro Digital',
       'California Polytechnic State University/NASA JPL',
       'University of Colorado',
       'University of Illinois Urbana-Champaign',
       'National Aeronautics and Space Administration (NASA)',
       'Department of Astrophysical and Planetary Science, UC Boulder/National Aeronautics and Space Administration (NASA)',
       'University of Michigan/NASA Earth Science Technology Office',
       'North Idaho STEM Charter Academy',
       'Massachusetts Institute of Technology',
       'DARPA (Defense Advanced Research Projects Agency)', 'DoD/NOAA',
       'University of Southern California, Space Engineering Research Center/Lockheed Martin',
       'Planet Labs, Inc.', 'Global Eagle Entertainment',
       'Echostar Satellite Services, LLC',
       'HughesNet leased from Echostar Technologies, LLC',
       'Echostar Satellite Services, LLC/Intelsat ', 'Momentus',
       'University of California',
       'Goddard Space Flight Center/EOS Data and Operations System',
       'ESPACE', 'Defense Advanced Research Projects Agency (DARPA)',
       'California Polytechnic Institute', 'US Air Force Academy',
       'University of Texas - Austin',
       'National Aeronautics and Space Administration (NASA)/GSFC',
       'Firebird Consortium (Montana State Univ., Univ. of New Hampshire, Aerospace Corp., Los Alamos National Laboratory)',
       'US Navy', 'Los Alamos National Laboratory',
       'PanAmSat (Intelsat S.A.)', 'Intelsat S.A.', 'Intelsat S.A. ',
       'PanAmSat (Intelsat S.A.)/DirecTV, Inc.',
       'Air Force Research Laboratory/Globalstar',
       'NearSpace Launch/Air Force Research Laboratory',
       'Bigelow Aerospace', 'DigitalGlobe Corporation', 'Globalstar',
       'PlanetiQ',
       'NOAA (National Oceanographic and Atmospheric Administration)',
       'Lunasonde', 'Air Force Satellite Control Network',
       'U.S. Army�s Space and Missile Defense Command',
       'Department of Defense/Army Space and Missile Defense Command',
       'Department of Defense/Space Test Program',
       'US Army Space and Missile Defense Command', 'HawkEye 360',
       'Space Sciences Laboratory, UC Berkeley/NASA',
       'Harris Corporation', 'European Space Agency (ESA)/NASA',
       'Intelsat S.A./Sky Perfect JSAT Corp.',
       'National Aeronautics and Space Administration (NASA)/Goddard Space Flight Center',
       'Iridium Communications, Inc.',
       'NASA Small Satellite Technology Program', 'NASA/CalPoly',
       'US Army Space and Missile Defense Command/Army Forces Strategic Command',
       'National Aeronautics and Space Administration (NASA)/US Geological Survey',
       'US Space Force', 'Spire Global Inc.',
       'California Polytechnic State University',
       'General Atomics Electromagnetic Systems', 'Lynk Global Inc.',
       'Northwest Nazarene University',
       'University of Michigan/Montana University',
       'National Reconnaissance Office (NRO)/US Air Force',
       'Analytical Space', 'Space Logistics LLC',
       'MIT/Lincoln Laboratory-University of Massachusetts Amherst',
       'DoD/US Navy', 'ACMEO', 'Tyvak Nanosatellite Systems, Inc.',
       'DoD/US Air Force',
       'National Oceanographic and Atmospheric Administration (NOAA) (part of international program)',
       'National Oceanographic and Atmospheric Administration (NOAA)/NASA',
       'F Space Test Office',
       'National Aeronautics and Space Administration (NASA)-Ames Research Center/Stanford University',
       'Michigan Technological University/Air Force Research Laboratory',
       'U.S. Space Force', 'ORBCOMM Inc.',
       'University of Texas at El Paso', 'DARPA/Tethers Unlimited',
       'Portland State Aerospace Society',
       'F /ORSO (Operationally Responsive Space Office)',
       'General Atomics - Electromagnetic Systems Group',
       'National Reconnaissance Office',
       'National Aeronautics and Space Administration (NASA)/Cornell University',
       'US Naval Academy', 'Helios Wire/Echostar Global Australia',
       'Tiger Innovations', 'Brigham Young University', 'US Coast Guard',
       'University of Colorado, Boulder', 'Naval Post-Graduate School',
       'Georgia Institute of Technology',
       'SES S.A. -- total capacity leased to subsidiary of EchoStar Corp. ',
       'Vanderbilt University/AMSAT',
       'Robertsville Middle School, Oak Ridge, Tennessee',
       'Applied Physics Laboratory/NASA',
       'Strategic Space Command/Space Surveillance Network',
       'National Reconnaissance Office (NRO)/US Navy',
       'University of North Carolina - Wilmington',
       'NASA Langley Research Center', 'SRI International',
       'Sirius XM Holdings', 'XM Satellite Radio ', 'LightSquared',
       'US Southern Command',
       'National Aeronautics and Space Administration (NASA) Earth Science Office/Laboratory for Atmospheric and Space Physics, Univ. of Colorado',
       'COSMIAC (Configurable Space Microsystems Innovations & Applications Center) ',
       'Swarm Technologies', 'Hughes Space and Communications Co. ',
       'Omnispace', 'SpaceX', 'Atlas 5', 'Missile Defense Agency (MDA)',
       'Naval Research Laboratory',
       'Operational Responsive Space (ORS) Office', 'Orbit Fab',
       'National Aeronautics and Space Administration (NASA)/SES Americom (SES [Soci�t� Europ�enne des Satellites (SES)])',
       'National Aeronautics and Space Administration (NASA)/Ames Research Center',
       'Colorado State University', 'TerraStar Corporation',
       'National Aeronautics and Space Administration (NASA)/Applied Physics Laboratory, Johns Hopkins',
       'UMBRA',
       'National Aeronautics and Space Administration (NASA)/Johns Hopkins University Applied Physics Laboratory',
       'Care Weather Technologies', 'ViaSat, Inc.',
       'NASA/Carnegie Mellon University',
       'Military Satellite Communications - US Air Force',
       'WildBlue Communications', 'Maxar Technologies Inc.',
       'Loft Orbital/Fugro', 'Loft Orbital'], dtype=object)
In [ ]:
sat_df['Age_Remaining'] = (sat_df['Year of Launch'] + sat_df['Expected Lifetime (yrs.)']) - 2023
sat_df.sort_values('Age_Remaining')
Out[ ]:
Name of Satellite, Alternate Names Current Official Name of Satellite Country/Org of UN Registry Country of Operator/Owner Operator/Owner Users Purpose Detailed Purpose Class of Orbit Type of Orbit ... Country of Contractor Launch Site Launch Vehicle COSPAR Number NORAD Number Comments alpha-3 Country_Code Year of Launch Age_Remaining
755 FLTSATCOM-8 (USA 46) USA 46 USA USA US Navy Military Communications NaN GEO NaN ... USA Cape Canaveral Atlas Centaur 1989-077A 20253 Old system replaced by UFO satellites; this sa... USA 840.0 1989 -29.0
2565 SCD-1 (Sat�lite de Coleta de Dados) SCD-1 Brazil Brazil Instituto Nacional de Pesquisas Espaciais (INPE) Government Earth Observation Meteorology/Earth Science LEO Non-Polar Inclined ... Brazil Cape Canaveral Pegasus 1993-009B 22491 Collects meteorological and environmental data... BRA 76.0 1993 -27.0
2683 Skynet 4C Skynet 4C United Kingdom United Kingdom Intelsat/Paradigm Secure Communications (wholl... Military Communications NaN GEO NaN ... France/UK/Germany Guiana Space Center Ariane 44LP 1990-079A 20776 Spare. In March 2010 it was announced that the... GBR 826.0 1990 -26.0
6298 TDRS-3 (Tracking and Data Relay Satellite, TDR... TDRS-3 USA USA National Aeronautics and Space Administration ... Government Communications NaN GEO NaN ... USA Cape Canaveral Space Shuttle (STS 26) 1988-091B 19548 Backup; still partially operational. USA 840.0 1988 -25.0
6440 UFO-4 (USA 108, UFO F4 EHF) "UHF Follow-On" USA 108 USA USA US Navy Military Communications NaN GEO NaN ... USA Cape Canaveral Atlas 2 1995-003A 23467 Ultra-High Frequency (UHF) communications and ... USA 840.0 1995 -24.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6710 Zhuhai 1-06 (OHS-3) OHS-3 China China Zhuhai Orbita Aerospace Science and Technology... Commercial Earth Observation Hyperspectral Imaging LEO Sun-Synchronous ... China Jiuquan Satellite Launch Center Long March 11 2018-040D 43442 Survey natural resources, cities, crops and fo... CHN 156.0 2018 NaN
6711 Zhuhai 1-07 (OHS-4) OHS-4 China China Zhuhai Orbita Aerospace Science and Technology... Commercial Earth Observation Hyperspectral Imaging LEO Sun-Synchronous ... China Jiuquan Satellite Launch Center Long March 11 2018-040E 43443 Survey natural resources, cities, crops and fo... CHN 156.0 2018 NaN
6712 Ziyuan 1-02C Ziyuan 1-02C China China China Centre for Resources Satellite Data and ... Government Earth Observation Optical Imaging LEO Sun-Synchronous ... China Taiyuan Launch Center Long March 4B 2011-079A 38038 Can acquire high-resolution data through remot... CHN 156.0 2011 NaN
6716 Ziyuan 3-3 Ziyuan 3-3 China China China Centre for Resources Satellite Data and ... Government Earth Observation Optical Imaging LEO Sun-Synchronous ... China Taiyuan Launch Center Long March 4B 2020-051A 45939 Land survey satellite. Provide data for the co... CHN 156.0 2020 NaN
6717 Z-Sat Z-Sat NR (1/22) Japan Mitsubishi Heavy Industries Commercial Technology Development NaN LEO Sun-Synchronous ... Japan Uchinoura Space Center H2A 2021-102E 49399 Testbed for a miniature lab module that could ... JPN 392.0 2021 NaN

6718 rows × 32 columns

In [ ]:
sat_df.iloc[1070]
Out[ ]:
Name of Satellite, Alternate Names    Hubble Space Telescope (HST, Space Telescope)
Current Official Name of Satellite                           Hubble Space Telescope
Country/Org of UN Registry                                                      USA
Country of Operator/Owner                                                       USA
Operator/Owner                                     European Space Agency (ESA)/NASA
Users                                                                    Government
Purpose                                                               Space Science
Detailed Purpose                                                                NaN
Class of Orbit                                                                  LEO
Type of Orbit                                                    Non-Polar Inclined
Longitude of GEO (degrees)                                                      0.0
Perigee (km)                                                                  555.0
Apogee (km)                                                                   559.0
Eccentricity                                                               0.000289
Inclination (degrees)                                                          28.5
Period (minutes)                                                               95.8
Launch Mass (kg.)                                                           11110.0
 Dry Mass (kg.)                                                                 NaN
Power (watts)                                                              2,400.00
Date of Launch                                                  1990-04-25 00:00:00
Expected Lifetime (yrs.)                                                       10.0
Contractor                                               European Space Agency/NASA
Country of Contractor                                                 International
Launch Site                                                          Cape Canaveral
Launch Vehicle                                               Space Shuttle (STS 31)
COSPAR Number                                                             1990-037B
NORAD Number                                                                  20580
Comments                                                      Exploration of space.
alpha-3                                                                         USA
Country_Code                                                                  840.0
Year of Launch                                                                 1990
Age_Remaining                                                                 -23.0
Name: 1070, dtype: object
In [ ]:
(1990+10)-2023
Out[ ]:
-23
In [ ]:
age_chart = alt.Chart(sat_df
  ).mark_boxplot().encode(
    x=alt.X('Purpose'),
    y=alt.Y('Age_Remaining'),
    color = 'Purpose:N',
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch']
)
age_chart
Out[ ]:
In [ ]:
age_chart_2 = alt.Chart(sat_df
  ).mark_point().encode(
    x=alt.X('Date of Launch'),
    y=alt.Y('Age_Remaining'),
    color = 'Purpose:N',
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Purpose', 'Date of Launch', 'Age_Remaining']
)
age_chart_2
Out[ ]:
In [ ]:
age_chart_3 = alt.Chart(sat_df
  ).mark_boxplot().encode(
    x=alt.X('Class of Orbit'),
    y=alt.Y('Age_Remaining'),
    color = 'Class of Orbit:N',
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch']
)
age_chart_3
Out[ ]:
In [ ]:
age_chart_4 = alt.Chart(sat_df
  ).mark_boxplot().encode(
    x=alt.X('Country of Operator/Owner'),
    y=alt.Y('Age_Remaining'),
    color = alt.Color('Country of Operator/Owner:N', legend = None),
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch', 'Age_Remaining']
)
age_chart_4
Out[ ]:
In [ ]:
top_k_grouped = sat_df.groupby('Country of Operator/Owner').size().reset_index(name = 'count').sort_values(by = 'count', ascending = False)
top_k_sat_df = pd.merge(top_k_grouped.head(10), sat_df, on = 'Country of Operator/Owner')
In [ ]:
top_k_sat_df
Out[ ]:
Country of Operator/Owner count Name of Satellite, Alternate Names Current Official Name of Satellite Country/Org of UN Registry Operator/Owner Users Purpose Detailed Purpose Class of Orbit ... Country of Contractor Launch Site Launch Vehicle COSPAR Number NORAD Number Comments alpha-3 Country_Code Year of Launch Age_Remaining
0 USA 4512 1HOPSAT-TD (1st-generation High Optical Perfor... 1HOPSAT-TD NR Hera Systems Commercial Earth Observation Infrared Imaging LEO ... USA Satish Dhawan Space Centre PSLV 2019-089H 44859 Pathfinder for planned earth observation const... USA 840.0 2019 -3.5
1 USA 4512 Advanced Orion 10 (Mentor, NRO L-44, USA 311) USA 311 USA National Reconnaissance Office (NRO) Military Earth Observation Electronic Intelligence GEO ... USA Cape Canaveral Delta 4 Heavy 2020-095A 47237 ELINT. USA 840.0 2020 NaN
2 USA 4512 Advanced Orion 4 (Mentor, NROL 6, USA 139) USA 139 USA National Reconnaissance Office (NRO) Military Earth Observation Electronic Intelligence GEO ... USA Cape Canaveral Titan IVA 1998-029A 25336 ELINT. USA 840.0 1998 NaN
3 USA 4512 Advanced Orion 5 (Mentor, NROL 19, USA 171) USA 171 USA National Reconnaissance Office (NRO) Military Earth Observation Electronic Intelligence GEO ... USA Cape Canaveral Titan IV 2003-041A 27937 Electronic intelligence (ELINT). USA 840.0 2003 NaN
4 USA 4512 Advanced Orion 6 (Mentor, NRO L-26, USA 202) USA 202 USA National Reconnaissance Office (NRO) Military Earth Observation Electronic Intelligence GEO ... USA Cape Canaveral Delta 4 Heavy 2009-001A 33490 ELINT. USA 840.0 2009 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
6207 Germany 48 TET-1 (Technologieerprobungstr�ger 1, Technolo... TET-1 Germany German Aerospace Center (DLR) Commercial Technology Development NaN LEO ... Germany Baikonur Cosmodrome Soyuz-Fregat 2012-039D 38710 Center of the OOV (On Orbit Verification) Prog... DEU 276.0 2012 -10.0
6208 Germany 48 TRSI-2 TRSI-2 NR(9/22) MyRadar Commercial Technology Development NaN LEO ... Germany/ Rocket Lab Launch Complex 1 Electron 2022-047AC 52420 NaN DEU 276.0 2022 0.0
6209 Germany 48 TRSI-3 TRSI-3 NR (9/22) MyRadar Commercial Technology Development NaN LEO ... Germany/ Rocket Lab Launch Complex 1 Electron 2022-047AA 52418 NaN DEU 276.0 2022 0.0
6210 Germany 48 TUBIN (Technische Universit�t Berlin) TUBIN NR (9/21) Technical University Berlin Civil Technology Demonstration NaN LEO ... Germany Cape Canaveral Falcon 9 2021-059X 48900 Primary objective to provide an on-orbit demon... DEU 276.0 2021 NaN
6211 Germany 48 UWE-4 (University of W�rzburg Experimental Sat... UWE-4 Germany University of W�rzburg Civil Technology Development/Educational NaN LEO ... Germany Vostochny Cosmodrome Soyuz-2.1a 2018-111E 43880 Demonstrate miniaturized electric propulsion s... DEU 276.0 2018 NaN

6212 rows × 33 columns

In [ ]:
age_chart_facet = alt.Chart(top_k_sat_df).mark_boxplot(ticks = True).encode(
    x = alt.X("Users:O", 
            title = None, 
            axis = alt.Axis(labels = False, ticks = False), 
            scale = alt.Scale(padding = 0.75)), 
    y = alt.Y("Age_Remaining:Q"), 
    color = alt.Color("Users:N", 
        legend = alt.Legend(
            orient = 'none',
            legendX = 350, legendY = -40,
            direction = 'horizontal',
            titleAnchor = 'middle')),
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite', 'Purpose', 'Date of Launch', 'Age_Remaining'])

# Create line to highlight 0 on y-axis.
line_plot = alt.Chart().mark_rule(color= 'black', opacity = 0.02
    ).encode(y = alt.Y('a:Q'))

alt.layer(age_chart_facet, line_plot, data = top_k_sat_df).facet(
    column = alt.Column('Country of Operator/Owner:N', 
        sort = ['USA'], 
        header = alt.Header(orient='bottom'))

).configure_facet(
    spacing = 0
).transform_calculate(
    a = '0'
).display()
In [ ]:
age_chart_5 = alt.Chart(sat_df
  ).mark_boxplot().encode(
    x=alt.X('Users'),
    y=alt.Y('Age_Remaining'),
    color = alt.Color('Users:N', legend = None),
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Date of Launch', 'Age_Remaining']
)
age_chart_5
Out[ ]:
In [ ]:
alt_chart = alt.Chart(sat_df
  ).mark_point().encode(
    x=alt.X('Perigee (km)'),
    y=alt.Y('Apogee (km)'),
    color = alt.Color('Class of Orbit:N'),
    opacity = alt.value(0.4),
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Perigee (km)','Apogee (km)','Class of Orbit']
)
alt_chart
Out[ ]:
In [ ]:
period_chart = alt.Chart(sat_df
  ).mark_boxplot().encode(
    x=alt.X('Class of Orbit'),
    y=alt.Y('Period (minutes)'),
    color = 'Class of Orbit:N',
    tooltip=['Country of Operator/Owner','Current Official Name of Satellite','Perigee (km)','Apogee (km)','Class of Orbit']
)
period_chart
Out[ ]:
In [ ]:
# map_df = sat_df.groupby(['Country of Operator/Owner', 'Country_Code']).size().sort_values(ascending = False).reset_index(name = 'count')
display(map_df)
# Map visualization to come later.
Country of Operator/Owner Country_Code count
0 USA 840.0 4512
1 China 156.0 587
2 United Kingdom 826.0 561
3 Russia 643.0 177
4 Japan 392.0 88
... ... ... ...
67 Hungary 348.0 1
68 Nepal 524.0 1
69 Iraq 368.0 1
70 Jordan 400.0 1
71 Kuwait 414.0 1

72 rows × 3 columns

In [ ]:
earth_radius = 6370
orbits_inc = list(zip(sat_df['Apogee (km)'], 
                      sat_df['Perigee (km)'], 
                      sat_df['Inclination (degrees)'].astype(float),
                      sat_df['Class of Orbit']))
In [ ]:
###
# Resources used:
# https://en.wikipedia.org/wiki/Orbital_elements
# https://en.wikipedia.org/wiki/Two-line_element_set
# Help with inclination orbit rotation - https://space.stackexchange.com/questions/44335/visualising-orbits-from-different-viewpoints-in-python
# 
###

def calc_ellipse(apogee, perigee, inclination_deg):

    earth_radius = 6370  # km
    inclination_rad = np.radians(inclination_deg)

    # Adjust altitudes into true apogee (distance to center of earth)
    # as data is assuming distance from surface, not center.
    apogee_adj = apogee + earth_radius
    perigee_adj = perigee + earth_radius

    # Calculating semi-major axis and eccentricity (we should check ecc. against data).
    a = (apogee_adj + perigee_adj) / 2
    e = (apogee - perigee) / (apogee_adj + perigee_adj)

    # Generate angles to find ellipse.
    angles = np.linspace(0, 2 * np.pi, 1000)

    # Calculating distance from Earth center for each angle.
    r = (a * (1 - (e ** 2))) / (1 + e * np.cos(angles))

    # Converting polar coords to Cartesian coords.
    x = r * np.cos(angles)
    y = r * np.sin(angles)

    # # Rotation matrix for inclination
    
    # # Z
    # rotation_matrix = np.array([
    #     [np.cos(inclination_rad), -np.sin(inclination_rad), 0],
    #     [np.sin(inclination_rad), np.cos(inclination_rad), 0],
    #     [0, 0, 1]
    # ])

    # # X
    # rotation_matrix = np.array([
    #     [1, 0, 0],
    #     [0, np.cos(inclination_rad), -np.sin(inclination_rad)],
    #     [0, np.sin(inclination_rad), np.cos(inclination_rad)]
        
    # ])

    # Y
    rotation_matrix = np.array([
        [np.cos(inclination_rad), 0, np.sin(inclination_rad)],
        [0, 1, 0],
        [-np.sin(inclination_rad), 0, np.cos(inclination_rad)]
        
    ])

    # Apply inclination to the orbit
    orbit = np.array([x, y, np.zeros_like(x)])
    rotated_orbit = np.matmul(rotation_matrix, orbit)

    x_rot, y_rot, z_rot = rotated_orbit # Don't need z for 2d.
    return (x_rot, y_rot)

plt.figure(figsize = (12, 12))

# Plotting the Earth at origin.
earth_circle = plt.Circle((0, 0), earth_radius, color = '#064273', alpha = 1, label = 'Earth')
plt.gca().add_patch(earth_circle)

# Create color mapping.
color_dict = {'Elliptical': '#64113F',
              'LEO': '#C73E1D',
              'MEO': '#385F71',
              'GEO': '#86BAA1'}

for i, j, k, orbit_class in orbits_inc:

    x, y = calc_ellipse(i, j, k)

    # Plotting the orbit.
    plt.plot(x, y, alpha = 0.3, color = color_dict[orbit_class])
    plt.title('2D View of Active Satellites Orbiting Earth')
    plt.xlabel('X-axis (km)')
    plt.ylabel('Y-axis (km)')
    plt.grid(True)
    plt.axis('equal')  # Set an equal aspect ratio

    cust_legend = [Line2D([0], [0], color = color_dict['LEO'], lw = 2),
                Line2D([0], [0], color = color_dict['MEO'], lw = 2),
                Line2D([0], [0], color = color_dict['GEO'], lw = 2),
                Line2D([0], [0], color = color_dict['Elliptical'], lw = 2)]
    plt.legend(cust_legend, ['Low Earth Orbit (LEO)', 'Middle Earth Orbit (MEO)', 'Geosynchronous Orbit (GEO)', 'Elliptical Orbit'])

plt.show()
In [ ]:
from mpl_toolkits.mplot3d import Axes3D

def calc_ellipse_3d(apogee, perigee, inclination_deg):

    # Constants
    earth_radius = 6370  # km

    # Given data
    apogee_adj = apogee + earth_radius
    perigee_adj = perigee + earth_radius
    inclination_rad = np.radians(inclination_deg)

    # Calculating semi-major axis and eccentricity
    a = (apogee_adj + perigee_adj) / 2
    e = (apogee - perigee) / (apogee_adj + perigee_adj)

    # Generating angles from 0 to 2*pi
    angles = np.linspace(0, 2 * np.pi, 1000)

    # Calculating distance from Earth center for each angle
    r = (a * (1 - (e ** 2))) / (1 + e * np.cos(angles))

    # Converting polar coordinates to Cartesian coordinates
    x = r * np.cos(angles)
    y = r * np.sin(angles)

    # Rotation matrix for inclination
    # # Z
    # rotation_matrix = np.array([
    #     [np.cos(inclination_rad), -np.sin(inclination_rad), 0],
    #     [np.sin(inclination_rad), np.cos(inclination_rad), 0],
    #     [0, 0, 1]
    # ])
    # # X
    # rotation_matrix = np.array([
    #     [1, 0, 0],
    #     [0, np.cos(inclination_rad), -np.sin(inclination_rad)],
    #     [0, np.sin(inclination_rad), np.cos(inclination_rad)]
        
    # ])
    # Y
    rotation_matrix = np.array([
        [np.cos(inclination_rad), 0, np.sin(inclination_rad)],
        [0, 1, 0],
        [-np.sin(inclination_rad), 0, np.cos(inclination_rad)]
        
    ])

    # Apply inclination to the orbit
    orbit = np.array([x, y, np.zeros_like(x)])
    rotated_orbit = np.matmul(rotation_matrix, orbit)

    x_rot, y_rot, z_rot = rotated_orbit
    return (x_rot, y_rot, z_rot)

# Creating a 3D plot
fig = plt.figure(figsize = (12, 12))
ax = fig.add_subplot(111, projection = '3d')

# # Plotting Earth
c = [0, 0, 0]
r = [earth_radius] # Radius of earth
u, v = np.mgrid[0:2 * np.pi:50j, 0:np.pi:50j]
x_e = r * np.cos(u) * np.sin(v)
y_e = r * np.sin(u) * np.sin(v)
z_e = r * np.cos(v)
ax.plot_surface(x_e - c[0], y_e - c[1], z_e - c[2], color= '#064273', alpha = 0.2)

# Create color mapping.
color_dict = {'Elliptical': '#64113F',
              'LEO': '#C73E1D',
              'MEO': '#385F71',
              'GEO': '#86BAA1'}

for i, j, k, orbit_class in orbits_inc:
    x, y, z = calc_ellipse_3d(i, j, k)

    # Plotting the orbit in a side-view perspective
    ax.plot(x, y, z, zdir='z', alpha = 0.3, color = color_dict[orbit_class])

# Set labels and title
ax.set_xlabel('X-axis (km)')
ax.set_ylabel('Y-axis (km)')
ax.set_zlabel('Z-axis (km)')
# ax.set_zlim(-360000, 360000)
# ax.set_xlim(-360000, 360000)
# ax.set_ylim(-360000, 360000)
ax.set_box_aspect([1,1,1])
ax.set_aspect('equal')
plt.title('3D View of Active Satellites Orbiting Earth')
#plt.legend()

cust_legend = [Line2D([0], [0], color = color_dict['LEO'], lw = 2),
                Line2D([0], [0], color = color_dict['MEO'], lw = 2),
                Line2D([0], [0], color = color_dict['GEO'], lw = 2),
                Line2D([0], [0], color = color_dict['Elliptical'], lw = 2)]
ax.legend(cust_legend, ['Low Earth Orbit (LEO)', 'Middle Earth Orbit (MEO)', 'Geosynchronous Orbit (GEO)', 'Elliptical Orbit'])

plt.show()

Visualization Project Part 3: A Plan for Evaluation¶


In your previous post, you identified a series of tasks and goals for your visualization as well as some preliminary design ideas. We’ll jump ahead a few steps and start to think about how we might evaluate our design approach. Outline a preliminary evaluation that addresses your core goals with the visualization. Make sure your evaluation discusses:

The target question you want to answer

The people you would recruit to answer that question

The kinds of measures you would use to answer your data (e.g., insight depth, use cases, accuracy) and what these measures would tell you about the core question

The approach you will use to answer that question (e.g., a journaling study, a formal experiment, etc.)

How you would instantiate those methods (i.e., what would your participants do?)

What criteria would you use to indicate that your visualization was successful

Part 3 Answers:¶

Evaluation Plan:¶
  • Task 1: Data overview displaying key features organized by country.

    • Target Question - What countries have the most active satellites? Of those top k countries what is the distribution in purpose of their active satellites? Are there any trends over time or across countries in their satellite distributions?
    • People to Recruit - As this visualization is intended to turn surface-level knowledge about current active satellites into deeper insights, I would recruit people ranging from non-experts to space science enthusiasts so I could properly measure insight depth.
    • Measures to be used to answer (e.g. insight depth, use cases, accuracy) - Insight depth would would be the most interesting measure as this visualization is meant to allow the user to drill down and make comparisons across groups. Use cases also would be a useful measure.
    • Specific Approach - Depending on whether this evaluation would be formative or summative, a "thinkaloud" or journaling study respectively. Following along with the user's stream of consciousness on how they utilize the tool to "snowball" intto deeper insights/questions would be important to understand what works or what needs to be adjusted or expanded.
    • Method of Instantiation - Users would be monitored and encouraged to think out loud while using the tool for a short period of time, then stopped and asked a few questions about insights or questions that are developing. The user then would be allowed to utilize the tool for a few minutes and asked to verbalize any insights or questions. These "thinkaloud" sessions would build a decision tree of sorts to further expand and improve the visualizations.
    • Criteria to Indicate Success - Just as the target questions set have different levels of insight required, the measure of success could be reached based on how deep of insights lead to which target questions along with the speed in which the deeper target questions are answered. Journaling results that indicate a wide range of use cases would also indicate success of the tool.
  • Task 2: Using dates of launch and life expectancy, display age statistics across features

    • Target Question - Of the countries with the most active satellites, which countries have an aging satellite fleet? What owner sectors tend to have older satellites?
    • People to Recruit - Science journalists, space science enthusiasts, or political scientists interested in different country's space capabilities.
    • Measures to be used to answer (e.g. insight depth, use cases, accuracy) - Accuracy of insights using specific questions related to the target question. In other words, how accurately users can identify correlations between variables in the data distributions organized by categorical variables.
    • Specific Approach - Perform an experiment to capture how accurately users are able to identify correlations between countries, life expectancy of satellite remaining, and sector. Analyze results to determine how effective the tool is.
    • Method of Instantiation - Users would spend time with the tool, then be presented with a questionnaire asking the target questions which would then be analyzed and the tool would be given a score based on user answers.
    • Criteria to Indicate Success - Users accurately identify distribution of age of satellites across the presented data. The ease and speed in which these insights are gained.
  • Task 3: Calculate and visualize orbital paths of active satellites, labeling orbital class.

    • Target Question - What type of orbit is the most common/congested (plane, distance)? Would you be able to identify different types of orbits?
    • People to Recruit -
    • Measures to be used to answer (e.g. insight depth, use cases, accuracy) -
    • Specific Approach -
    • Method of Instantiation -
    • Criteria to Indicate Success -

About the Final Project¶


Throughout the Modules, you have found a dataset, characterized the corresponding goals and tasks you want to conduct with that data, designed preliminary approaches, and outlined how you would evaluate those approaches. For your final project, you will put these ideas into practice by executing on the project plan outlined in your prior posts.

For this project, you will implement a visualization using your data from Module 1 and preliminary low-fidelity prototypes from Module 2 to address your stated goals. You may implement this visualization using either Altair or another platform of your choice. Once implemented, conduct your evaluation based on the plan outlined in your Module 3 discussion post, making sure to conduct your evaluation with at least three people. You may refine any of your prior plan to reflect your evolving understanding of the challenges you are addressing. Be sure to address how your plan has changed from these earlier posts as part of your discussion.

Your final project post should include:

A brief recap of your data, goals, and tasks, focusing on those that most directly influence your design

Screenshots of and/or a link to your visualization implementation (see below for additional guidance)

A summary of the key elements of your design and accompanying justification

A discussion of your final evaluation approach, including the procedure, people recruited, and results. Note that, due to the difficulty of recruiting experts, you can use colleagues, friends, classmates, or family to evaluate your designs if experts or others from your target population are unavailable.

A synthesis of your findings, including what elements of your approach worked well and what elements you would refine in future iterations.

Guidance and platforms for deploying Altair visualizations online include:

Altair: Interactive Plots on the Web

Add Animated Charts To Your Dashboards With Streamlit-Python

Creating Interactive Jupyter Notebooks and Deployment on Heroku Using Voila

Survey Questionnaire¶

Proceed through these questions and

  1. Spend a maximum of 5-10 seconds with the visualization to get an initial impression and answer the following questions.
    • What is one piece of information you learned.
    • Using a little imagination, who would utilize/benefit most from this data representation?
  2. Now revisit the visualization and verbalize anything you notice.
    • Starting from the most basic and then to more complex, what insights have you captured now that you've explored it further?
    • After spending some time with the visualization, are there any further questions/deeper insights that wish had been answered?
    • Are there any specific elements that were or weren't successful?
  3. Answer target questions from Cody (did they or are they able to answer the target question?).

Sqyds¶

Task 1¶

    • ESA = European Space Agency, USA has the most active satellites, China and UK are nearly equal.
    • Governments, private companies looking to compete with SpaceX.
    • SpaceX has the vast majority of satellites, Majority of Russian satellite operators are from the government, not as many multinational as they would expect, Large increase of launches in 2021-22 in USA and China while UK cut their launches in half during the same period in time, The majority of US satellite functionality is used for communications.
      • Deeper understanding of specifics in what the categories of functionality are, why there was a spike in launches between the last 2 years.
      • Successes: Interactivity in selecting the bar, colors are nice and easy to read/distinguish between.
      • Failures: None!

Task 2¶

1. - ¶

2. - ¶

- 
- 

3.